using System;
using System.Data;
using System.Data.Common;
using System.Windows.Forms;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.OleDb;


namespace Tilver.DBConnectionUI.Editors
{
    [ToolboxItem(false)]
    internal partial class OleDbEditor : UserControl, IUDLEditor, IOleDbEditor
	{
        OleDbConnectionStringBuilder _builder = new OleDbConnectionStringBuilder();

		public OleDbEditor()
		{
			InitializeComponent();

            this.txDataSource.Validated += delegate { this.SetValue("Data Source", this.txDataSource.Text);};
            this.txLocation.Validated += delegate { this.SetValue("Location", this.txLocation.Text);};
            this.txUserID.Validated += delegate { this.SetValue("User Id", this.txUserID.Text);};
            this.txPassword.Validated += delegate { this.SetValue("Password", this.txPassword.Text);};
            this.txInitialCatalog.Validated += delegate { this.SetValue("Initial Catalog", this.txInitialCatalog.Text);};
            this.ckPersistSecurityInfo.CheckedChanged += delegate { this.SetValue("Persist Security Info", this.ckPersistSecurityInfo.Checked);};

        }

        #region IConnectionEditor Members

        public string ConnectionString
        {
            get
            {
                return _builder.ConnectionString;
            }
            set
            {
                try
                {
                    _builder.ConnectionString = value;
                    UpdateControls();
                }
                catch (Exception) { }
                this.RefreshData();
            }
        }

        public void RefreshData()
        {
            this.txDataSource.Text = Convert.ToString(GetValue("Data Source"));
            this.txUserID.Text = Convert.ToString(GetValue("User Id"));
            this.txPassword.Text = Convert.ToString(GetValue("Password"));
            this.txInitialCatalog.Text = Convert.ToString(GetValue("Initial Catalog"));
            this.ckPersistSecurityInfo.Checked = Convert.ToBoolean(this.GetValue("Persist Security Info"));

        }

        public object GetAdvancedPropertiesObject()
        {
            ObjectWrapper wrapper = new ObjectWrapper(_builder);
            wrapper.HiddenProperties.Add("Provider");
            wrapper.HiddenProperties.Add("ConnectionString");
            return wrapper;
        }

        #endregion

        #region IOleDbEditor Members

        public void SetOleProviderID(string invariantName)
        {
            _builder.Provider = invariantName;
        }

        #endregion

        #region helper methods

        void UpdateControls()
        {

            this.txDataSource.Enabled = this.ContainsProperty("Data Source");
            this.txLocation.Enabled = this.ContainsProperty("Location");
            this.cmdFindLocation.Enabled = this.txLocation.Enabled;
            this.txUserID.Enabled = (this.ContainsProperty("User Id") ||
                                     this.ContainsProperty("UID"));
            this.txPassword.Enabled = (this.ContainsProperty("Password") ||
                                     this.ContainsProperty("PWD"));
            this.ckPersistSecurityInfo.Enabled = this.ContainsProperty("Persist Security Info");
            this.txInitialCatalog.Enabled = this.ContainsProperty("Initial Catalog");
        }

        void FindFilename(object sender, EventArgs e)
        {
            OpenFileDialog fd = new OpenFileDialog();
            if (fd.ShowDialog(this) == DialogResult.OK)
            {
                this.SetValue("Location", fd.FileName);
                txLocation.Text = fd.FileName;
            }
        }

        void cmdFindDatasource_Click(object sender, EventArgs e)
        {
            OpenFileDialog fd = new OpenFileDialog();
            if (fd.ShowDialog() == DialogResult.OK)
            {
                SetValue("Data Source", fd.FileName);
                txDataSource.Text = _builder.DataSource;
            }
        }

        void SetValue(string key, object value)
        {
            // null string values need to be reset 
            // to avoid empty connection properties
            if (value == null || (value is string && value.ToString().Length == 0))
            {
                if (_builder.ContainsKey(key))
                    this.ResetProperty(key);
            }
            else
            {
                // if the current value is the same as the default value
                // we will reset the property
                PropertyDescriptor prop = this.FindProperty(key);
                if (prop != null)
                {
                    DefaultValueAttribute att = this.FindDefaultAttribute(prop);
                    if (att != null && att.Value.Equals(value))
                    {
                        if (_builder.ContainsKey(key))
                        {
                            this.ResetProperty(key);
                        }
                        return;
                    }
                }

                if (_builder.ContainsKey(key))
                    _builder[key] = value;
                else
                    _builder.Add(key, value);
            }

            if (key == "Provider")
            {
                UpdateControls();
            }
        }

        object GetValue(string key)
        {
            PropertyDescriptor prop = this.FindProperty(key);
            if (prop != null)
            {
                return prop.GetValue(_builder);
            }
            return null;
        }

        bool ContainsProperty(string key)
        {
            return (this.FindProperty(key) != null);
        }

        void ResetProperty(string key)
        {
            if (_builder.ContainsKey(key))
                _builder[key] = null;
            _builder.Remove(key);
        }

        PropertyDescriptor FindProperty(string displayName)
        {
            foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(_builder))
            {
                if (prop.DisplayName.Equals(displayName, StringComparison.OrdinalIgnoreCase))
                    return prop;
            }
            return null;
        }

        DefaultValueAttribute FindDefaultAttribute(PropertyDescriptor prop)
        {
            foreach (Attribute att in prop.Attributes)
            {
                if (att is DefaultValueAttribute)
                    return att as DefaultValueAttribute;
            }
            return null;
        }

        #endregion
    }
}
